package org.wmq.travelagency02.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wmq.travelagency02.constant.OrderStatusConstant;
import org.wmq.travelagency02.constant.SignUpStatusConstant;
import org.wmq.travelagency02.mapper.SignUpMapper;
import org.wmq.travelagency02.model.Entity.Order;
import org.wmq.travelagency02.model.Entity.SignUp;
import org.wmq.travelagency02.model.Entity.TourGroup;
import org.wmq.travelagency02.model.Entity.Traveller;
import org.wmq.travelagency02.model.VO.SignUpQueryByTourGroupIdVO;
import org.wmq.travelagency02.model.VO.SignUpQueryByTravellerIdVO;
import org.wmq.travelagency02.model.VO.SignUpQueryVO;
import org.wmq.travelagency02.service.*;

import java.util.List;

@Service
@RequiredArgsConstructor
public class SignUpServiceImpl extends ServiceImpl<SignUpMapper, SignUp> implements SignUpService {
    private final SignUpMapper signUpMapper;
    @Lazy
    @Autowired
    private TravellerService travellerService;
    @Autowired
    private TourGroupService tourGroupService;
    private final OrderService orderService;

    @Override
    public SignUpQueryVO getSignUpInfoByTravellerIdAndTourGroupId(Long travellerId, Long tourGroupId) {
        SignUp signUp = this.lambdaQuery().eq(SignUp::getTravellerId, travellerId)
                .eq(SignUp::getTourGroupId, tourGroupId)
                .select(SignUp::getStatus).one();
        if (signUp == null){
            return null;
        }
        SignUpQueryVO result = new SignUpQueryVO();
        result.setStatus(signUp.getStatus());

        Traveller traveller = this.travellerService.lambdaQuery().eq(Traveller::getId, travellerId)
                .select(Traveller::getName, Traveller::getPhone
                        , Traveller::getAge, Traveller::getGender).one();
        traveller.setId(travellerId);

        TourGroup tourGroup = this.tourGroupService.lambdaQuery().eq(TourGroup::getId, tourGroupId)
                .select(TourGroup::getName, TourGroup::getPrice, TourGroup::getBeginTime,
                        TourGroup::getEndTime, TourGroup::getMaxSize, TourGroup::getStatus,
                        TourGroup::getRouteId,TourGroup::getGuidebookId).one();
        tourGroup.setId(tourGroupId);

        result.setTraveller(traveller);
        result.setTouGroup(tourGroup);

        return result;
    }

    @Override
    public SignUpQueryByTravellerIdVO getSignUpInfoByTravellerId(Long travellerId) {
        List<SignUp> signUpList = this.lambdaQuery().eq(SignUp::getTravellerId, travellerId).
                select(SignUp::getStatus, SignUp::getTourGroupId).list();
        if (signUpList == null || signUpList.size() == 0){
            return null;
        }

        List<TourGroup> tourGroupList = this.tourGroupService.lambdaQuery().
                in(TourGroup::getId, signUpList.stream().map(signUp -> signUp.getTourGroupId())).
                select(TourGroup::getId,TourGroup::getName,TourGroup::getPrice).
                list();

        SignUpQueryByTravellerIdVO result = new SignUpQueryByTravellerIdVO();
        result.setSignUpList(signUpList);
        result.setTourGroupList(tourGroupList);

        return result;
    }

    @Override
    public SignUpQueryByTourGroupIdVO getSignUpInfoByTourGroupId(Long tourGroupId) {
        List<SignUp> signUpList = this.lambdaQuery().eq(SignUp::getTourGroupId, tourGroupId).
                select(SignUp::getStatus, SignUp::getTravellerId).list();
        if (signUpList == null || signUpList.size() == 0){
            return null;
        }

        List<Traveller> travellerList = this.travellerService.lambdaQuery().
                in(Traveller::getId, signUpList.stream().map(signUp -> signUp.getTravellerId())).
                select(Traveller::getId,Traveller::getName,Traveller::getPhone).
                list();

        SignUpQueryByTourGroupIdVO result = new SignUpQueryByTourGroupIdVO();
        result.setSignUpList(signUpList);
        result.setTravellerList(travellerList);

        return result;
    }

    @Override
    public boolean removeByTravellerId(Long travellerId) {
        return this.lambdaUpdate().eq(SignUp::getTravellerId, travellerId).remove();
    }

    @Override
    public boolean removeByTourGroupId(Long tourGroupId) {
        return this.lambdaUpdate().eq(SignUp::getTourGroupId, tourGroupId).remove();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSignUpById(SignUp signUp) {
        if (signUp.getStatus() == SignUpStatusConstant.SUCCESS){
            Order order = new Order();
            order.setTourGroupId(signUp.getTourGroupId());
            order.setTravellerId(signUp.getTravellerId());
            order.setStatus(OrderStatusConstant.UNPAID);
            order.setAmount(this.tourGroupService.getPriceById(signUp.getTourGroupId()));
            boolean success = this.orderService.save(order);
            if (!success){
                throw new RuntimeException("更新报名状态时发生异常，新增订单失败");
            }
        }
        return this.lambdaUpdate().eq(SignUp::getTravellerId, signUp.getTravellerId())
                .eq(SignUp::getTourGroupId, signUp.getTourGroupId()).update(signUp);
    }
}
